#ifndef UmlClassItem_H
#define UmlClassItem_H

#include <QDebug>

#include <QRectF>
#include <QPainter>
#include <QStyleOptionGraphicsItem>
#include <QVariant>
#include <QList>

#include "uml/class/classattribute.h"
#include "uml/class/classmethod.h"
#include "uml/umlrelationalitem.h"
#include "uml/umldiritem.h"
#include "gui/editors/classeditor.h"
#include "uml/relations/buttons/associationbutton.h"
#include "uml/relations/buttons/kompositionbutton.h"
#include "uml/pen/realizationrelationpen.h"
#include "uml/class/umlclassheader.h"

#define TEXT_HEADER_PADDING 20
#define TEXT_ATT_H_PADDING 5
#define TEXT_ATT_V_PADDING 5

#define CLASS_BORDER_COLOR "#173FF7"
#define CLASS_BG_COLOR_0_0 "#62B5FD"
#define CLASS_BG_COLOR_0_5 "#DBEDFD"
#define CLASS_BG_COLOR_1_0 "#FFFFFF"

#define INTERFACE_BORDER_COLOR "#2A801C"
#define INTERFACE_BG_COLOR_0_0 "#65FF51"
#define INTERFACE_BG_COLOR_0_5 "#EAFFD6"
#define INTERFACE_BG_COLOR_1_0 "#FFFFFF"

#define ABS_CLASS_BORDER_COLOR "#000000"
#define ABS_CLASS_BG_COLOR_0_0 "#CCCCCC"
#define ABS_CLASS_BG_COLOR_0_5 "#F3F3F3"
#define ABS_CLASS_BG_COLOR_1_0 "#FFFFFF"


class UmlClassItem : public UmlRelationalItem
{
    friend class ClassAttribute;
    friend class ClassMethod;

    Q_OBJECT

public:
    UmlClassItem(UmlProject *project = 0);
    ~UmlClassItem();

    void setText(QString name);

    QRectF nameRect() const;

    void appendAtt(ClassAttribute *att);
    QList<ClassAttribute*> attList();
    void removeAtt(ClassAttribute *att);
    bool hasAttribute(ClassAttribute *att);

    void appendMeth(ClassMethod *meth);
    QList<ClassMethod*> methList();
    void removeMeth(ClassMethod *meth);
    bool hasMethod(ClassMethod * meth);

    bool isInterface();
    void setIsInterface(bool isInterface);

    bool isAbstract();
    void setIsAbstract(bool isAbstract);

    bool isClass();

    bool showAtts();
    void setShowAtts(bool show);

    bool showMeths();
    void setShowMeths(bool show);

    bool hasAttributes();
    bool hasMethods();

    void appendRelation(UmlRelation *relation, UmlRelation::RelativeItemPosition direction);
    void removeRelation(UmlRelation *relation, UmlRelation::RelativeItemPosition direction);

    QList<UmlRelation*> parentClasses();
    QList<UmlRelation*> realizedInterfaces();
    QList<UmlRelation*> allAssociations();

    bool checkRelation(UmlRelation *possibleRelation, UmlRelationalItem *possibleRelationPartner);

    void updateBoundingBox();

    void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
    void hoverMoveEvent(QGraphicsSceneHoverEvent *event);
    void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);

    void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);

    virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value);

    QList<QAction*> contextActions();

protected:
    QList<ClassAttribute*> _attList;
    QList<ClassMethod*> _methList;

    QMap<UmlRelation::RelativeItemPosition,RelationPort*> _generalizationPorts;
    QMap<UmlRelation::RelativeItemPosition,RelationPort*> _realizationPorts;

    bool _isInterface;
    bool _isAbstract;

    // Colors & Pens
    QPen _whitePen;
    QLinearGradient _gradient;


    // bounding rects
    QRectF _headerRect;
    QRectF _attRect;
    QRectF _methRect;
    QRectF _bodyRect;
    QRectF _highlightRect;
    qreal minWidth();

    UmlTextChildItem *_itemUnderMouse;

    QGraphicsLineItem _headerAttBorderItem;
    QGraphicsLineItem _attMethBorderItem;

    UmlClassHeader _headerGraphicsItem;

    UmlTextChildItem* findItemUnderMouse(QPointF pos);

    int countPorts(UmlRelation::RelativeItemPosition direction);

    bool _showAtts;
    bool _showMeths;

    void removeInvalidRelations();

public slots:
    void openClassEditor();
    void openAttributeEditor(ClassAttribute *attribute = 0);
    void openMethodEditor(ClassMethod *method = 0);
    void toggleIsClass();
    void toggleIsInterface();
    void toggleIsAbstract();
    void toggleShowAtts();
    void toggleShowMeths();
};

#endif // UmlClassItem_H
